package com.mf.basic.excel;

import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * 合并单元格， 按某一列的相同项规则，合并其他列
 */
public class ExcelFillCellMergeStrategy_1 implements CellWriteHandler {

    private int startColumnIndex;
    private int mergeRowIndex;
    private int endColumnIndex;

    public ExcelFillCellMergeStrategy_1() {
    }

    public ExcelFillCellMergeStrategy_1(int mergeRowIndex, int startColumnIndex, int endColumnIndex) {
        this.mergeRowIndex = mergeRowIndex;
        this.startColumnIndex = startColumnIndex;
        this.endColumnIndex = endColumnIndex;
    }


    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> list, Cell cell, Head head, Integer integer, Boolean aBoolean) {
        //当前行
        int curRowIndex = cell.getRowIndex();
        //当前列
        int curColIndex = cell.getColumnIndex();
        if (curRowIndex > mergeRowIndex && curColIndex == startColumnIndex) {
            mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, startColumnIndex, endColumnIndex);
        }
    }



    /**
     * 当前单元格向上合并
     *
     * @param cell             当前单元格
     * @param curRowIndex      当前行
     * @param startColumnIndex  合并参考列
     * @param endColumnIndex  合并终止列
     */
    private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int startColumnIndex, int endColumnIndex) {
        //获取当前行的当前列的数据和上一行的当前列列数据，通过上一行数据是否相同进行合并
        Object curData = cell.getCellType() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue();
        Row row = cell.getSheet().getRow(curRowIndex - 1);
        if(null == row){
            return;
        }
        Cell preCell = row.getCell(startColumnIndex);
        Object preData = preCell.getCellType() == CellType.STRING ? preCell.getStringCellValue() : preCell.getNumericCellValue();

        // 比较当前行的第一列的单元格与上一行是否相同，相同合并当前单元格与上一行
        if (curData.equals(preData)) {
            Sheet sheet = writeSheetHolder.getSheet();
            List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();
            boolean isMerged = false;
            int k = 0;
            List<CellRangeAddress> addList = new ArrayList<>();
            List<Integer> delList = new ArrayList<>();
            for (int i = 0; i < mergeRegions.size() && !isMerged; i++) {
                CellRangeAddress cellRangeAddr = mergeRegions.get(i);
                // 若上一个单元格已经被合并，则先移出原有的合并单元，再重新添加合并单元
                if (cellRangeAddr.isInRange(curRowIndex - 1, startColumnIndex + k)) {
                    delList.add(i);
                    //sheet.removeMergedRegion(i);
                    cellRangeAddr.setLastRow(curRowIndex);
                    addList.add(cellRangeAddr);
                    //sheet.addMergedRegion(cellRangeAddr);
                    k++;
                    if(k > (endColumnIndex - startColumnIndex)){
                        isMerged = true;
                    }
                }
            }
            if(!CollectionUtils.isEmpty(delList)){
                sheet.removeMergedRegions(delList);
            }
            if(!CollectionUtils.isEmpty(addList)){
                for(CellRangeAddress obj : addList){
                    sheet.addMergedRegion(obj);
                }
            }
            // 若上一个单元格未被合并，则新增合并单元
            if (!isMerged) {
                CellRangeAddress cellRangeAddress;
                for(int j=startColumnIndex; j<=endColumnIndex; j++){
                    cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, j, j);
                    sheet.addMergedRegion(cellRangeAddress);
                }

            }
        }
    }

    @Override
    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer integer, Integer integer1, Boolean aBoolean) {

    }

    @Override
    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer integer, Boolean aBoolean) {

    }
}

